package com.example.rockscissorspapergame.page.slice;

import com.example.rockscissorspapergame.Constants;
import com.example.rockscissorspapergame.ResourceTable;
import com.example.rockscissorspapergame.dialog.DeviceDialog;
import com.example.rockscissorspapergame.page.MainAbility;
import com.example.rockscissorspapergame.service.ConnectionHelper;
import com.example.rockscissorspapergame.service.RemoteProxy;
import com.example.rockscissorspapergame.service.ServiceAbility;
import com.example.rockscissorspapergame.utils.DeviceUtils;
import com.example.rockscissorspapergame.utils.GameUtils;
import com.example.rockscissorspapergame.utils.ToastUtils;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.ability.IAbilityConnection;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.Operation;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.Text;
import ohos.bundle.ElementName;
import ohos.rpc.IRemoteObject;

/**
 * 游戏主页面
 */
public class MainAbilitySlice extends AbilitySlice {

    /**
     * 跨端连接代理，用于发送跨端消息
     */
    private static RemoteProxy mRemoteProxy = null;

    /**
     * 武器按钮点击监听
     */
    private final WeaponClickListener mWeaponClickListener = new WeaponClickListener();

    /**
     * 界面上的组件
     */
    private Text mTextTitle;
    private Button mButtonStartRemote;
    private Text mTextMainDeviceId;
    private Text mTextRemoteDeviceId;
    private Text mTextConnectStatus;
    private Text mTextMainWeapon;
    private Text mTextRemoteWeapon;
    private Text mTextWinner;
    private Button mButtonRock;
    private Button mButtonScissors;
    private Button mButtonPaper;

    /**
     * 标识当前应用是否运行在主机端
     */
    private boolean isMainDevice = true;

    /**
     * 主机端设备 ID
     */
    private String mMainDeviceId;
    /**
     * 远程端设备 ID
     */
    private String mRemoteDeviceId;

    /**
     * 主机端选择的武器（石头、剪刀、布）
     */
    private String mMainWeapon = Constants.EMPTY_STRING;
    /**
     * 远程端选择的武器（石头、剪刀、布）
     */
    private String mRemoteWeapon = Constants.EMPTY_STRING;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);

        // 获取当前页面类型，true 为主机端，false 为远程端，默认为 true
        isMainDevice = intent.getBooleanParam(Constants.PARAM_KEY_IS_MAIN_DEVICE, true);

        if (isMainDevice) {
            // 获取主机端ID
            mMainDeviceId = DeviceUtils.getLocalDeviceId(getContext());
        } else {
            // 获取传递过来的主机端设备 ID
            mMainDeviceId = intent.getStringParam(Constants.PARAM_KEY_MAIN_DEVICE_ID);
            // 获取远程端设备 ID
            mRemoteDeviceId = DeviceUtils.getLocalDeviceId(getContext());
        }
        // 初始化界面上的组件
        initComponents();
        // 向 ConnectionHelper 注册回调，用于接收跨端消息
        ConnectionHelper.getInstance().setCallback(this::handleMessage);
    }

    @Override
    public void onActive() {
        super.onActive();
        if (!isMainDevice) {
            connectService(mMainDeviceId);
        }
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }

    /**
     * 初始化界面组件
     */
    private void initComponents() {
        // 实例化界面上的组件
        mTextTitle = (Text) findComponentById(ResourceTable.Id_text_title);
        mButtonStartRemote = (Button) findComponentById(ResourceTable.Id_button_start_remote);
        mTextMainDeviceId = (Text) findComponentById(ResourceTable.Id_text_main_device_id);
        mTextRemoteDeviceId = (Text) findComponentById(ResourceTable.Id_text_remote_device_id);
        mTextConnectStatus = (Text) findComponentById(ResourceTable.Id_text_connect_status);
        mTextMainWeapon = (Text) findComponentById(ResourceTable.Id_text_main_weapon);
        mTextRemoteWeapon = (Text) findComponentById(ResourceTable.Id_text_remote_weapon);
        mTextWinner = (Text) findComponentById(ResourceTable.Id_text_winner);
        mButtonRock = (Button) findComponentById(ResourceTable.Id_button_rock);
        mButtonScissors = (Button) findComponentById(ResourceTable.Id_button_scissors);
        mButtonPaper = (Button) findComponentById(ResourceTable.Id_button_paper);

        // 显示主机端设备 ID
        mTextMainDeviceId.setText(mMainDeviceId);

        // 为用于显示主机端设备 ID 的 Text 组件设置跑马灯效果
        mTextMainDeviceId.setTruncationMode(Text.TruncationMode.AUTO_SCROLLING);
        mTextMainDeviceId.setAutoScrollingCount(Text.AUTO_SCROLLING_FOREVER);
        mTextMainDeviceId.startAutoScrolling();
        // 为石头按钮设置点击监听
        mButtonRock.setClickedListener(mWeaponClickListener);
        // 为剪刀按钮设置点击监听
        mButtonScissors.setClickedListener(mWeaponClickListener);
        // 为布按钮设置点击监听
        mButtonPaper.setClickedListener(mWeaponClickListener);
        // 判断当前页面是主机端还是远程端，并对页面做出修改
        if (isMainDevice) {
            // 为启动远程端按钮设置点击监听，点击可以展示设备对话框
            mButtonStartRemote.setClickedListener(component -> showDeviceDialog());
        } else {
            mTextTitle.setText("远程端页面");
            // 隐藏“启动远程端”按钮
            mButtonStartRemote.setVisibility(Component.HIDE);
            // 显示远程端设备ID
            mTextRemoteDeviceId.setText(mRemoteDeviceId);
            // 为用于显示远程端设备 ID 的 Text 组件设置跑马灯效果
            mTextRemoteDeviceId.setTruncationMode(Text.TruncationMode.AUTO_SCROLLING);
            mTextRemoteDeviceId.setAutoScrollingCount(Text.AUTO_SCROLLING_FOREVER);
            mTextRemoteDeviceId.startAutoScrolling();
        }
    }

    /**
     * 展示设备选择弹窗，弹窗上展示所有支持分布式的设备，用户选择设备后可以进行跨设备迁移
     */
    private void showDeviceDialog() {
        DeviceDialog deviceDialog = new DeviceDialog(getContext(), deviceInfo -> {
            mRemoteDeviceId = deviceInfo.getDeviceId();
            startRemotePage(mRemoteDeviceId);
            mTextRemoteDeviceId.setText(mRemoteDeviceId);
            mTextRemoteDeviceId.setTruncationMode(Text.TruncationMode.AUTO_SCROLLING);
            mTextRemoteDeviceId.setAutoScrollingCount(Text.AUTO_SCROLLING_FOREVER);
            mTextRemoteDeviceId.startAutoScrolling();

            // 连接远程端 Service
            connectService(mRemoteDeviceId);
        });

        deviceDialog.show();
    }

    /**
     * 刷新游戏状态
     */
    private void refreshGameStatus() {
        if (GameUtils.isTextEmpty(mMainWeapon)) {
            mTextMainWeapon.setText("未出拳");
            mTextMainWeapon.setAroundElements(null, null, null, null);
        } else {
            mTextMainWeapon.setText("出" + mMainWeapon);
            mTextMainWeapon.setAroundElements(null, null, GameUtils.getWeaponElement(getContext(), mMainWeapon), null);
        }
        if (GameUtils.isTextEmpty(mRemoteWeapon)) {
            mTextRemoteWeapon.setText("未出拳");
            mTextRemoteWeapon.setAroundElements(null, null, null, null);
        } else {
            mTextRemoteWeapon.setText("出" + mRemoteWeapon);
            mTextRemoteWeapon.setAroundElements(null, null, GameUtils.getWeaponElement(getContext(), mRemoteWeapon), null);
        }
        // 比赛结果（主机端胜利、远程端胜利）
        String gameResult = GameUtils.getGameResult(mMainWeapon, mRemoteWeapon);
        mTextWinner.setText(gameResult);
    }

    /**
     * 不同武器按钮的统一点击监听
     */
    private class WeaponClickListener implements Component.ClickedListener {
        @Override
        public void onClick(Component component) {
            String weapon;
            // 根据点击按钮的不同，选取不同的拳头常量
            if (component == mButtonRock) {
                weapon = Constants.GAME_WEAPON_ROCK;
            } else if (component == mButtonScissors) {
                weapon = Constants.GAME_WEAPON_SCISSORS;
            } else if (component == mButtonPaper) {
                weapon = Constants.GAME_WEAPON_PAPER;
            } else {
                return;
            }
            if (isMainDevice) {
                mMainWeapon = weapon;
            } else {
                mRemoteWeapon = weapon;
            }
            // 刷新当前页面状态
            refreshGameStatus();
            // 跨端发送武器信息
            sendMessage(weapon);
        }
    }

    private void startRemotePage(String remoteDeviceId) {
        if (mMainDeviceId == null || mMainDeviceId.isEmpty()) {
            ToastUtils.showToast(getContext(), "本机设备 ID 获取失败");
        }
        Intent intent = new Intent();
        Operation operation = new Intent.OperationBuilder()
                .withDeviceId(remoteDeviceId)
                .withBundleName(getBundleName())
                .withAbilityName(MainAbility.class.getName())
                .withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE)
                .build();
        intent.setOperation(operation);
        intent.setParam(Constants.PARAM_KEY_IS_MAIN_DEVICE, false);
        intent.setParam(Constants.PARAM_KEY_MAIN_DEVICE_ID, mMainDeviceId);
        startAbility(intent);
    }

    /**
     * 接收并处理收到的跨端信息
     *
     * @param message 跨端信息
     */
    private void handleMessage(String message) {
        // 切换到主线程
        getUITaskDispatcher().asyncDispatch(() -> {
            // 根据收到的消息更新界面
            if (isMainDevice) {
                // 如果当前是主机端页面，则收到的是远程端武器
                mRemoteWeapon = message;
            } else {
                // 如果当前是远程端页面，则收到的是主机端武器
                mMainWeapon = message;
            }
            // 刷新界面
            refreshGameStatus();
        });
    }

    /**
     * 连接主机端的Service，用来向主机端发送信息
     *
     * @param deviceId 跨端连接 Service 时需要提供的设备 ID
     */
    private void connectService(String deviceId) {
        Intent intent = new Intent();
        Operation operation = new Intent.OperationBuilder()
                .withDeviceId(deviceId)
                .withBundleName(getBundleName())
                .withAbilityName(ServiceAbility.class.getName())
                .withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE)
                .build();
        intent.setOperation(operation);
        // 使用 Intent 连接远程端 Service
        connectAbility(intent, connection);
    }

    /**
     * 发送跨端消息
     *
     * @param message 消息内容
     */
    private void sendMessage(String message) {
        if (  mRemoteProxy == null) {
            // 若跨端连接代理尚未被实例化，则无法发送消息，此时通过 Toast 提示用户
            ToastUtils.showToast(getContext(), "无跨端连接代理");
        } else {
            // 通过跨端连接代理发送消息
            mRemoteProxy.sendMessage(message);
        }
    }

    /**
     * IAbilityConnection 实例，用于建立到 Service 的连接
     */
    private final IAbilityConnection connection = new IAbilityConnection() {
        @Override
        public void onAbilityConnectDone(ElementName elementName, IRemoteObject iRemoteObject, int i) {
            // 连接成功，实例化跨端连接代理
            mRemoteProxy = new RemoteProxy(iRemoteObject);
            getUITaskDispatcher().asyncDispatch(() -> mTextConnectStatus.setText("已连接"));
        }

        @Override
        public void onAbilityDisconnectDone(ElementName elementName, int i) {
        }
    };
}
